﻿using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace 线扫相机Demo
{

    

    public class CameraUtil
    {

        //private static void ImageBaseDataToBitmap(ImageBaseData mvImage, out Bitmap image)
        //{
        //    int width = mvImage.Width;
        //    int height = mvImage.Height;
        //    uint dataLen = mvImage.DataLen;
        //    byte[] imageData = mvImage.ImageData;
        //    //ImagePixelFOrmat:17301505 代表灰度图片；35127316 代表彩色图片
        //    int imgPixelFormat = mvImage.Pixelformat;

        //    if (imgPixelFormat == ImageData.IMVS_PIX_MONO8)
        //    {
        //        image = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
        //        BytesToBitmap8(width, height, imageData, out image);
        //    }
        //    else if (imgPixelFormat == ImageData.IMVS_PIX_RGB8_PACKED)
        //    {
        //        image = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        //        BytesToBitmap24(width, height, imageData, out image);
        //    }
        //    else
        //    {
        //        //其他类型暂未实现
        //        throw new Exception("只实现了8位灰度图片和24位彩色图片，其他类型未实现。");
        //        //return;
        //    }
        //}

        private static void BytesToBitmap8(int width, int height, byte[] data, out Bitmap target)
        {
            target = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            BitmapData bmpData = target.LockBits(new Rectangle(0, 0, target.Width, target.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

            //获取图像参数
            int stride = bmpData.Stride;  // 扫描线的宽度  
            int offset = stride - width;  // 显示宽度与扫描线宽度的间隙  
            IntPtr ptrBmp = bmpData.Scan0;  // 获取bmpData的内存起始位置  
            int scanBytes = stride * height;// 用stride宽度，表示这是内存区域的大小  

            //下面把原始的显示大小字节数组转换为内存中实际存放的字节数组
            int posScan = 0, posReal = 0;// 分别设置两个位置指针，指向源数组和目标数组  
            byte[] pixelValues = new byte[scanBytes];  //为目标数组分配内存  

            for (int x = 0; x < height; x++)
            {
                //下面的循环节是模拟行扫描
                for (int y = 0; y < width; y++)
                {
                    pixelValues[posScan++] = data[posReal++];
                }
                posScan += offset;  //行扫描结束，要将目标位置指针移过那段“间隙”  
            }

            //用Marshal的Copy方法，将刚才得到的内存字节数组复制到BitmapData中
            Marshal.Copy(pixelValues, 0, ptrBmp, scanBytes);
            target.UnlockBits(bmpData);  // 解锁内存区域  

            //下面的代码是为了修改生成位图的索引表，从伪彩修改为灰度
            ColorPalette tempPalette;
            using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
            {
                tempPalette = tempBmp.Palette;
            }
            for (int i = 0; i < 256; i++)
            {
                tempPalette.Entries[i] = Color.FromArgb(i, i, i);
            }

            target.Palette = tempPalette;

        }

        private static void BytesToBitmap24(int width, int height, byte[] data, out Bitmap target)
        {
            target = new Bitmap(width, height, PixelFormat.Format24bppRgb);
            BitmapData bmpData = target.LockBits(new Rectangle(0, 0, target.Width, target.Height), ImageLockMode.ReadWrite, target.PixelFormat);
            IntPtr ptrBmp = bmpData.Scan0;
            int imageStride = target.Width * 3;
            if (imageStride == bmpData.Stride)
            {
                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {
                        byte chRed = data[i * width * 3 + j * 3];
                        data[i * width * 3 + j * 3] = data[i * width * 3 + j * 3 + 2];
                        data[i * width * 3 + j * 3 + 2] = chRed;
                    }
                }
                Marshal.Copy(data, 0, ptrBmp, bmpData.Stride * target.Height);
            }
            else
            {
                for (int i = 0; i < target.Height; ++i)
                {
                    Marshal.Copy(data, i * imageStride, new IntPtr(ptrBmp.ToInt64() + i * bmpData.Stride), target.Width);
                }
            }
            target.UnlockBits(bmpData);

        }

    }
}
